<?php

/**
 * @package XmlSpreadsheet
 * @author Aleksey Voronoy <aleksey.voronoy@gmail.com>
 */
class XmlSpreadsheetWorksheet {

	/**
	 * @var string
	 */
	private $name;
	private $tmplWorksheet = '<Worksheet %s><Table>%s</Table></Worksheet>';
	private $data = array();
	private $dataStyle = array();
	private $styles = array();

	function  __construct($name = '') {
		$this->setName($name);
	}

	/**
	 * @param string $name
	 * @assert ('test1) == 'test1'
	 */
	public function setName($name = '') {
		$this->name = $name;
		return $this->name;
	}

	/**
	 * @return string
	 */
	public function getName() {
		return $this->name;
	}

	public function render() {
		return sprintf($this->tmplWorksheet, $this->getWorksheetName(), $this->getData());
	}

	public function setValue($row, $column, $value) {
		if (!is_int($row) || !is_int($column)) {
			trigger_error('Wrong cell coordinates: (' . $row . ', ' . $column . ')');
			return false;
		}
		if ($row <= 0 || $column <= 0) {
			trigger_error('Wrong cell coordinates: (' . $row . ', ' . $column . ')');
			return false;
		}
		$this->data[$row][$column] = $value;
		return true;
	}

	public function setStyle($row, $column, $styles = array()) {
		$_styles = array(
			'Font' => array(
				'Bold',
				'Color',
				'FontName',
				'Italic',
				'Size',
				'StrikeThrough',
				'Underline',
				'VerticalAlign',
			)
		);
		if (!is_int($row) || !is_int($column)) {
			trigger_error('Wrong cell coordinates: (' . $row . ', ' . $column . ')');
			return false;
		}
		if ($row <= 0 || $column <= 0) {
			trigger_error('Wrong cell coordinates: (' . $row . ', ' . $column . ')');
			return false;
		}
		if (empty($styles)) {
			return false;
		}
		$styleHash = preg_replace('/[^A-Za-z0-9]/', '', $this->name) . md5(serialize($styles));
		if (!array_key_exists($styleHash, $this->styles)) {
			$style = '';
			foreach ($styles as $group => $attributes) {
				$style .= '<' . $group;
				if (array_key_exists($group, $_styles)) {
					foreach ($attributes as $attribute => $value) {
						if (in_array($attribute, $_styles[$group])) {
							$style .= ' ss:' . $attribute . '="' . $value . '"';
						}
					}
				}
				$style .= '/>';
			}
			$this->styles[$styleHash] = $style;
		}
		$this->dataStyle[$row][$column] = $styleHash;
		return true;

	}

	private function getWorksheetName() {
		if (empty($this->name)) {
			return '';
		} else {
			return 'ss:Name="' . htmlentities($this->name, ENT_QUOTES, 'UTF-8') . '"';
		}
	}

	private function getData() {
		if (empty($this->data)) {
			return '';
		}
		$data = '';
		ksort($this->data, SORT_NUMERIC);
		foreach ($this->data as $row => $cells) {
			if (empty($cells)) continue;
			$data .= '<Row ss:Index="' . $row . '">';
			ksort($cells, SORT_NUMERIC);
			foreach ($cells as $cell => $value) {
				$tmplCell = '<Cell ss:Index="%s" %s>';
				$data .= sprintf($tmplCell, $cell, $this->getCellStyle($row, $cell));
				if (is_numeric($value)) {
					$data .= '<Data ss:Type="Number">';
					$data .= $value;
				} else {
					$data .= '<Data ss:Type="String">';
					$data .= htmlentities($value, ENT_QUOTES, 'UTF-8');
				}
				$data .= '</Data>';
				$data .= '</Cell>';
			}
			$data .= '</Row>';
		}
		return $data;
	}

	private function getCellStyle($row, $column) {
		if (isset($this->dataStyle[$row]) && isset($this->dataStyle[$row][$column])) {
			return 'ss:StyleID="' . $this->dataStyle[$row][$column] . '"';
		} else {
			return '';
		}
	}

	public function getStyles() {
		if (empty($this->styles)) {
			return '';
		}
		$styles = '';
		foreach ($this->styles as $styleId => $style) {
			$styles .= '<Style ss:ID="' . $styleId . '">' . $style . '</Style>';
		}
		return $styles;
	}


}

?>